﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Data;
using l1cs.server.model.skill;
using l1cs.server.utils;

namespace l1cs.server.datatables
{
    public class SprTable
    {
        private static Logger _log = Logger.getLogger( typeof( SprTable ).FullName );

        private class Spr
        {
            public Dictionary<int, int> moveSpeed = new Dictionary<int, int>();

            public Dictionary<int, int> attackSpeed = new Dictionary<int, int>();

            public int nodirSpellSpeed = 1200;

            public int dirSpellSpeed = 1200;
        }

        private static Dictionary<int, Spr> _dataMap = new Dictionary<int, Spr>();

        private static SprTable _instance;

        public static SprTable getInstance()
        {
            if ( _instance == null )
            {
                _instance = new SprTable();
            }
            return _instance;
        }

        private SprTable()
        {/*TTOK*/
            Spr spr = null;
            String sqlstr = "SELECT * FROM spr_action";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                foreach ( DataRow item in wrapper.GetDataTable(sqlstr).Rows )
                {
                    int key = SqlUtils.toInt( item["spr_id"] );
                    if ( !_dataMap.ContainsKey( key ) )
                    {
                        spr = new Spr();
                        _dataMap[key] = spr;
                    }
                    else
                    {
                        _dataMap.TryGetValue( key, out spr );
                    }

                    int actid = SqlUtils.toInt( item["act_id"] );
                    int frameCount = SqlUtils.toInt( item["framecount"] );
                    int frameRate = SqlUtils.toInt( item["framerate"] );
                    // フレーム数とフレームレートからアクションの合計時間(ms)を計算して返す。
                    int speed = (int)( frameCount * 40 * ( 24D / frameRate ));

                    switch ( actid )
                    {
                        case ActionCodes.ACTION_Walk:
                        case ActionCodes.ACTION_SwordWalk:
                        case ActionCodes.ACTION_AxeWalk:
                        case ActionCodes.ACTION_BowWalk:
                        case ActionCodes.ACTION_SpearWalk:
                        case ActionCodes.ACTION_StaffWalk:
                        case ActionCodes.ACTION_DaggerWalk:
                        case ActionCodes.ACTION_TwoHandSwordWalk:
                        case ActionCodes.ACTION_EdoryuWalk:
                        case ActionCodes.ACTION_ClawWalk:
                        case ActionCodes.ACTION_ThrowingKnifeWalk:
                            spr.moveSpeed[actid] = speed;
                            break;
                        case ActionCodes.ACTION_SkillAttack:
                            spr.dirSpellSpeed = speed;
                            break;
                        case ActionCodes.ACTION_SkillBuff:
                            spr.nodirSpellSpeed = speed;
                            break;
                        case ActionCodes.ACTION_Attack:
                        case ActionCodes.ACTION_SwordAttack:
                        case ActionCodes.ACTION_AxeAttack:
                        case ActionCodes.ACTION_BowAttack:
                        case ActionCodes.ACTION_SpearAttack:
                        case ActionCodes.ACTION_StaffAttack:
                        case ActionCodes.ACTION_DaggerAttack:
                        case ActionCodes.ACTION_TwoHandSwordAttack:
                        case ActionCodes.ACTION_EdoryuAttack:
                        case ActionCodes.ACTION_ClawAttack:
                        case ActionCodes.ACTION_ThrowingKnifeAttack:
                            spr.attackSpeed[actid] = speed;
                            break;
                        default:
                            break;
                    }
                }
            }
            _log.config( "SPRデータ " + _dataMap.Count + "件ロード" );
        }

        /// <summary>
        /// 指定されたsprの攻撃速度を返す。
        /// もしsprに指定されたweapon_typeのデータが 
        /// 設定されていない場合は、1.attackのデータを返す。
        /// </summary>
        /// <param name="sprid">調べるsprのID</param>
        /// <param name="actid">武器の種類を表す値。L1Item.getType1()の返り値 + 1 と一致する</param>
        /// <returns>指定されたsprの攻撃速度(ms)</returns>
        public int getAttackSpeed( int sprid, int actid )
        {/*TTOK*/
            if ( _dataMap.ContainsKey( sprid ) )
            {
                if ( _dataMap[sprid].attackSpeed.ContainsKey( actid ) )
                {
                    return _dataMap[sprid].attackSpeed[actid];
                }
                else if ( actid == ActionCodes.ACTION_Attack )
                {
                    return 0;
                }
                else
                {
                    return _dataMap[sprid].attackSpeed[ActionCodes.ACTION_Attack];
                }
            }
            return 0;
        }

        public int getMoveSpeed( int sprid, int actid )
        {/*TTOK*/
            if ( _dataMap.ContainsKey( sprid ) )
            {
                if ( _dataMap[sprid].moveSpeed.ContainsKey( actid ) )
                {
                    return _dataMap[sprid].moveSpeed[actid];
                }
                else if ( actid == ActionCodes.ACTION_Walk )
                {
                    return 0;
                }
                else
                {
                    return _dataMap[sprid].moveSpeed[ActionCodes.ACTION_Walk];
                }
            }
            return 0;
        }

        public int getDirSpellSpeed( int sprid )
        {/*TTOK*/
            if ( _dataMap.ContainsKey( sprid ) )
            {
                return _dataMap[sprid].dirSpellSpeed;
            }
            return 0;
        }

        public int getNodirSpellSpeed( int sprid )
        {/*TTOK*/
            if ( _dataMap.ContainsKey( sprid ) )
            {
                return _dataMap[sprid].nodirSpellSpeed;
            }
            return 0;
        }
    }
}
